#include "transparent_mode.h"
#include <iostream>
#include <chrono>
#include <thread>


transparent_mode::transparent_mode(const std::string& serial_port)
    : running(false)
{
    if (!serial.open_port(serial_port)) {
        throw std::runtime_error("Failed to open serial port: " + serial_port);
    }
    serial.configure_port(460800, 8, 1, 'N', false);
}

transparent_mode::~transparent_mode()
{
}



// 启动透传相关线程
void transparent_mode::start() 
{
    running = true;
    send_thread = std::thread(&transparent_mode::sending_thread, this);
    recv_thread = std::thread(&transparent_mode::receiving_thread, this);
    //process_thread = std::thread(&transparent_mode::processing_thread, this);
}

// 停止透传相关线程
void transparent_mode::stop() 
{
    running = false;
    if (send_thread.joinable()) send_thread.join();
    if (recv_thread.joinable()) recv_thread.join();
    //if (process_thread.joinable()) process_thread.join();
    serial.close_port();
}


void transparent_mode::send_bytes_data(unsigned char *p_data, int len)
{
    //使用 lock_guard 自动管理互斥锁，获取发送互斥锁
    std::lock_guard<std::mutex> lock(send_mtx);

    std::vector<unsigned char> data(p_data, p_data + len);
    send_queue.push_back(data);
    send_cv.notify_one(); // 通知发送线程有新数据
}


//发送线程，从队列取出数据进行发送
void transparent_mode::sending_thread() 
{
    while (running) {
        std::unique_lock<std::mutex> lock(send_mtx);    //获取发送互斥锁
        
        send_cv.wait(lock, [this]() { return !send_queue.empty() || !running; });    //等待发送条件成立

        if (!running && send_queue.empty()) break;

        std::vector<unsigned char> data = send_queue.front();
        send_queue.pop_front();

        lock.unlock();    //手动释放发送互斥锁

        //调用串口发送数据
        serial.send_byte_data(data.data(), static_cast<int>(data.size()));


        //std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

// 接收线程：负责接收串口数据并放入接收队列
void transparent_mode::receiving_thread() 
{
    int bytes_read = -1;
    unsigned char read_buff[256];

    while (running)
    {
        bytes_read = serial.recv_data_poll(read_buff, sizeof(read_buff));  //从串口接收数据
        
        if(bytes_read > 0)    //读取到数据
        {
            //std::cout << "bytes_read = " << static_cast<int>(bytes_read) << std::endl;

            std::vector<unsigned char> vec(read_buff, read_buff+bytes_read);

            std::lock_guard<std::mutex> lock(recv_mtx);    //获取接收互斥锁

//            std::cout << "receiving data: ";
//            for(auto byte : vec)
//            {
//                std::cout << std::hex << static_cast<int>(byte) << " ";
//            }
//            std::cout << std::endl;

            recv_queue.push_back(vec);    //放入数据接收队列

            recv_cv.notify_one();  // 唤醒处理线程
            
        }
        
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }

}

// 处理线程：负责从接收队列中取出数据并处理
void transparent_mode::processing_thread() 
{
    static unsigned int count = 0;
    while (running) 
    {
        std::unique_lock<std::mutex> lock(recv_mtx);    //获取接收互斥锁
        recv_cv.wait(lock, [this]() { return !recv_queue.empty() || !running; });    //等待条件成立

        if (!running) break;

        std::vector<unsigned char> data = recv_queue.front();    //取出数据
        recv_queue.pop_front();    //移除队列第一个数据
        lock.unlock();    //手动释放互斥锁

        #if 0

        count += data.size();
        std::cout << "all data size : " << count << " ";
        //处理这些数据
        std::cout << "proccessing data: ";
        for(auto byte : data)
        {
            std::cout << std::hex << static_cast<int>(byte) << " ";
        }
        std::cout << std::endl;

        this->send_bytes_data(data.data(), static_cast<int>(data.size()));    //loop back

        #endif
    }
}

int transparent_mode::read_bytes_poll(unsigned char *p_data, int len)
{
    int read_count = 0;
    int count = 0;
    do
    {
        std::unique_lock<std::mutex> lock(recv_mtx);    //获取接收互斥锁
        //recv_cv.wait(lock, [this]() { return !recv_queue.empty();});    //等待条件成立

        if(!recv_queue.empty())
        {
            std::vector<unsigned char> data = recv_queue.front();    //取出数据
            recv_queue.pop_front();    //移除队列第一个数据
            lock.unlock();    //手动释放互斥锁

            if(data.size() <= static_cast<size_t>(len))
            {
                memcpy(p_data, data.data(), data.size());
                read_count = static_cast<int>(data.size());
            }
            else
            {
                memcpy(p_data, data.data(), static_cast<size_t>(len));
                read_count = len;
            }

            #if 0

            count += data.size();
            std::cout << "all data size : " << count << " ";
            //处理这些数据
            std::cout << "proccessing data: ";
            for(auto byte : data)
            {
                std::cout << std::hex << static_cast<int>(byte) << " ";
            }
            std::cout << std::endl;

            this->send_bytes_data(data.data(), static_cast<int>(data.size()));    //loop back

            #endif
        }



    }while(0);

    return read_count;
}
